/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package mathma.core.print;

import mathma.core.bool.*;
import mathma.core.calc.*;
import mathma.core.expr.*;
import mathma.core.form.*;
import mathma.core.real.*;
import mathma.core.real.form.*;
import mathma.core.vector.*;

/**
 * @since 0.2.6
 * @author Ethan Levine
 */
public class PlainPrinter extends AbstractPrinter {

    public static final PlainPrinter printer = new PlainPrinter();

    private PlainPrinter() {
        super();

        // bool values.
        link(BooleanValue.class, new Printer<BooleanValue>() {
            public String prints(BooleanValue bool) {
                return bool.getRawValue() ? "true" : "false";
            }
        });

        // bool formulaic.
        link(AndExpression.class, new FormPrinter("", " AND ", "", true));
        link(OrExpression.class, new FormPrinter("", " OR ", "", true));
        link(NotExpression.class, new FormPrinter("NOT ", "", "", true));
        link(TrueCountExpression.class, new FormPrinter("TRUE_COUNT(", ", ",
                ")", true));

        // TODO - calc forms

        // variables.
        link(RealVariable.class, new Printer<RealVariable>() {
            public String prints(RealVariable var) {
                return var.symbol();
            }
        });
        link(RealConstant.class, new Printer<RealConstant>() {
            public String prints(RealConstant c) {
                return c.symbol();
            }
        });

        // unary wrapped expr
        link(UnaryWrappedExpression.class, new Printer<UnaryWrappedExpression>() {
            public String prints(UnaryWrappedExpression e) {
                return print(e.getBackingExpr());
            }
        });

        // real values.
        link(FiniteReal.class, new Printer<FiniteReal>() {
            public String prints(FiniteReal real) {
                return real.bigDecimalValue().toString();
            }
        });
        link(InfiniteReal.class, new Printer<InfiniteReal>() {
            public String prints(InfiniteReal real) {
                return real.isPositive() ? "+INF" : "-INF";
            }
        });
        link(IndeterminateReal.class, new Printer<IndeterminateReal>() {
            public String prints(IndeterminateReal real) {
                return "<?:" + real.getReason().toString() + ">";
            }
        });
        link(mathma.core.real.Integer.class, FiniteReal.class);
        
        // real forms (alphabetically).
        link(AbsoluteValueExpression.class, new FormPrinter("|", "|", false));
        link(AdditionExpression.class, new FormPrinter("", " + ", "", true));
        link(CeilingExpression.class, new FormPrinter("CEILING("));
        link(CosecantExpression.class, new FormPrinter("csc("));
        link(CosineExpression.class, new FormPrinter("cos("));
        link(CotangentExpression.class, new FormPrinter("cot("));
        link(DivisionExpression.class, new FormPrinter("", " / ", "", true));
        link(ExponentialExpression.class, new FormPrinter("e^("));
        link(FactorialExpression.class, new FormPrinter("(", ")!", false));
        link(FloorExpression.class, new FormPrinter("FLOOR("));
        link(HyperbolicCosecantExpression.class, new FormPrinter("csch("));
        link(HyperbolicCosineExpression.class, new FormPrinter("cosh("));
        link(HyperbolicCotangentExpression.class, new FormPrinter("coth("));
        link(HyperbolicSecantExpression.class, new FormPrinter("sech("));
        link(HyperbolicSineExpression.class, new FormPrinter("sinh("));
        link(HyperbolicTangentExpression.class, new FormPrinter("tanh("));
        link(InverseCosecantExpression.class, new FormPrinter("arccsc("));
        link(InverseCosineExpression.class, new FormPrinter("arccos("));
        link(InverseCotangentExpression.class, new FormPrinter("arccot("));
        link(InverseHyperbolicCosecantExpression.class, new FormPrinter("arccsch("));
        link(InverseHyperbolicCosineExpression.class, new FormPrinter("arccosh("));
        link(InverseHyperbolicCotangentExpression.class, new FormPrinter("arccoth("));
        link(InverseHyperbolicSecantExpression.class, new FormPrinter("arcsech("));
        link(InverseHyperbolicSineExpression.class, new FormPrinter("arcsinh("));
        link(InverseHyperbolicTangentExpression.class, new FormPrinter("arctanh("));
        link(InverseSecantExpression.class, new FormPrinter("arcsec("));
        link(InverseSineExpression.class, new FormPrinter("arcsin("));
        link(InverseTangentExpression.class, new FormPrinter("arctan("));
        link(MultiplicationExpression.class, new FormPrinter("", " * ", "", true));
        link(NaturalLogarithmExpression.class, new FormPrinter("ln("));
        link(NegationExpression.class, new FormPrinter("-("));
        link(PowerExpression.class, new FormPrinter("", "^", "", true));
        link(ReciprocalExpression.class, new FormPrinter("1 / ("));
        link(SecantExpression.class, new FormPrinter("sec("));
        link(SineExpression.class, new FormPrinter("sin("));
        link(SquareRootExpression.class, new FormPrinter("sqrt("));
        link(SubtractionExpression.class, new FormPrinter("", " - ", "", true));
        link(TangentExpression.class, new FormPrinter("tan("));
        link(TruncationExpression.class, new FormPrinter("TRUNCATE("));
    }
}
